// 导入axios模块
import axios from 'axios'
import JSONbig from 'json-bigint'
import { Toast } from 'vant'
import router from '@/router'

// 导入vuex 容器(数据共享)组件
import store from '@/store'

const refreshTokenReq = axios.create({
  baseURL: 'http://ttapi.research.itcast.cn/'
})

// 创建axios实例
const Axios = axios.create({
  baseURL: 'http://ttapi.research.itcast.cn',
  // baseURL: 'http://api-toutiao-web.itheima.net',
  transformResponse: [function (data) {
    // 后端返回的数据可能不是 JSON 格式字符串
    // 如果不是的话，那么 JSONbig.parse 调用就会报错
    // 所以我们使用 try-catch 来捕获异常，处理异常的发生
    try {
      // 如果转换成功，则直接把结果返回
      return JSONbig.parse(data)
    } catch (err) {
      // console.log('转换失败', err)
      // 如果转换失败了，则进入这里
      // 我们在这里把数据原封不动的直接返回给请求使用
      return data
    }

    // axios 默认在内部使用 JSON.parse 来转换处理原始数据
    // return JSON.parse(data)
  }]
})

// axios请求拦截器
Axios.interceptors.request.use(config => {
  // 如果用户已登录，统一给接口设置 token 信息
  const user = store.state.user
  if (user) {
    config.headers.Authorization = `Bearer ${user.token}`
  }

  // 处理完之后一定要把 config 返回，否则请求就会停在这里
  return config
}, error => {
  return Promise.reject(error)
})

// axios响应拦截器
Axios.interceptors.response.use(response => {
  // 成功
  return response
}, async err => {
  // 对响应错误做点什么
  const status = err.response.status
  if (status === 400) {
    // 客户端请求参数错误
    Toast.fail('客户端请求参数异常')
  } else if (status === 401) {
    // token无效
    const user = store.state.user
    // 既没有token , 和 refresh_token直接跳转到登录页面
    if (!user || !user.token) {
      // 直接跳转到登录页
      return redirectLogin()
    }
    try {
      // 存在refresh_token 存在, 请求调用接口, 获取最新token
      const res = await refreshTokenReq({
        method: 'PUT',
        url: '/app/v1_0/authorizations',
        headers: {
          Authorization: `Bearer ${user.refresh_token}`
        }
      })
      // 获取最新token ,并替换之前token
      user.token = res.data.data.token
      store.commit('setUser', user)
      // 把失败的请求重新发出去
      // error.config 是本次请求的相关配置信息对象
      // 这里使用 request 发请求，它会走自己的拦截器
      // 它的请求拦截器中通过 store 容器访问 token 数据
      return Axios(err.config)
    } catch (err) {
      // 刷新 token 都失败了，直接跳转登录页
      redirectLogin()
    }
    Toast.fail('token无效')
  } else if (status === 403) {
    // 无权限
    Toast.fail('没有权限操作')
  } else if (status >= 500) {
    // 服务端异常
    Toast.fail('服务端异常，请稍后重试')
  }
  return Promise.reject(err)
})

// 重定向路由
function redirectLogin () {
  // push(产生历史)
  // replace(不产生历史)
  router.replace('/login')
}

// 导出
export default Axios
